#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import os

from common.const import ParamConstant, ExecuteResultEnum
from common.common import output_execution_result_ex
from common.common_models import ActionResult

from generaldb.saphana.restore.saphana_restore_tenant import SaphanaRestoreTenant
from generaldb.saphana.restore.saphana_restore_systemdb import SaphanaRestoreSystemDb
from generaldb.saphana.restore.saphana_parse_restore_params import SaphanaParseRestoreParam
from generaldb.saphana.comm.saphana_const import SaphanaJsonConstant, SaphanaJobType
from generaldb.saphana.comm.saphana_file_operate import log


class SaphanaRestoreService:
    def __init__(self, pid, job_id, subjob_id):
        self._pid = pid
        self._job_id = job_id
        self._subjob_id = subjob_id
        self._parse_param = SaphanaParseRestoreParam(pid, job_id, subjob_id)

    @staticmethod
    def output_action_result_ex(pid, code_param=0, body_err_param=0, message_param=""):
        """
        将actionResult写入到结果文件,供框架读取
        :return: 
        """
        json_result = ActionResult(code=code_param, bodyErr=body_err_param, message=message_param).\
            dict(by_alias=True)
        file_path = os.path.join(ParamConstant.RESULT_PATH, f"result{pid}")
        log.info(f"Write file. result:{code_param} {body_err_param} {message_param}")
        output_execution_result_ex(file_path, json_result)

    def init_restore_db(self):
        # 根据恢复的是系统数据库，还是租户数据库来初始化数据库对象
        restore_tenant_db = SaphanaRestoreTenant(self._pid, self._job_id, self._subjob_id, self._parse_param)
        restore_system_db = SaphanaRestoreSystemDb(self._pid, self._job_id, self._subjob_id, self._parse_param)
        if not restore_tenant_db or not restore_system_db:
            raise Exception(f"init restore db. pid:{self._pid} jobid:{self._job_id}") 
        if restore_tenant_db.is_system_db():
            return restore_system_db
        return restore_tenant_db

    def allow_restore_in_local_node(self):
        try:
            restore_db = self.init_restore_db()
        except Exception as exception_str:
            log.info(f"Init restore db failed. pid:{self._pid} jobid:{self._job_id}")
            return False
        if not restore_db:
            self.output_action_result_ex(self._pid, ExecuteResultEnum.INTERNAL_ERROR.value)
            return False
        
        body_err_param = 0
        ret = restore_db.allow_restore_in_local_node()
        if not ret:
            tmp_code = ExecuteResultEnum.INTERNAL_ERROR.value
            body_err_param = restore_db.get_errcode()
        else:
            tmp_code = ExecuteResultEnum.SUCCESS.value
        self.output_action_result_ex(self._pid, tmp_code, body_err_param)
        return True

    def exec_sub_job_comm(self, key):
        try:
            restore_db = self.init_restore_db()
        except Exception as exception_str:
            log.info(f"Init restore db failed. pid:{self._pid} jobid:{self._job_id}")
            return False
        if not restore_db:
            log.error(f"Init restore db failed. jobid:{self._job_id}")
            return False
        try:
            ret = restore_db.exec_sub_job(key)
        except Exception as exception_str:
            log.exception(exception_str)
            restore_db.report_success_or_failed(False, key)
            return False
        restore_db.report_success_or_failed(ret, key)
        return ret

    def restore_prerequisite(self):
        return self.exec_sub_job_comm(SaphanaJobType.RESTORE_PREDECESSOR)

    def restore_gen_sub_job(self):
        try:
            restore_db = self.init_restore_db()
        except Exception as exception_str:
            log.info(f"Init restore db failed. pid:{self._pid} jobid:{self._job_id}")
            return False
        if not restore_db:
            self.output_action_result_ex(self._pid, ExecuteResultEnum.INTERNAL_ERROR.value)
            return False
        sub_job_array = restore_db.gen_sub_job()
        if not sub_job_array:
            self.output_action_result_ex(self._pid, ExecuteResultEnum.INTERNAL_ERROR.value)
            return False
        else:
            file_path = os.path.join(ParamConstant.RESULT_PATH, f"result{self._pid}")
            output_execution_result_ex(file_path, sub_job_array)
            return True

    def restore(self):
        return self.exec_sub_job_comm(SaphanaJobType.RESTORE_RESTORE)

    def restore_post_job(self):
        return self.exec_sub_job_comm(SaphanaJobType.RESTORE_POST)

